/*
 * Copyright (C) 2021 XXXX Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import app from '@system.app'
import inputMethod from '@ohos.inputmethod'
import factory from '@ohos.data.distributedData'
import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index'

const KEY_TEST_STRING_ELEMENT = 'key_test_string_001';
const VALUE_TEST_STRING_ELEMENT = 'value_test_string-001';
const TEST_BUNDLE_NAME = 'ohos.acts.kvStore';
const TEST_STORE_ID = 'storeId';

var kvManager = null;
var kvStore = null;

function GetAverage(sum) {
    let sums = 0;
    for (let i = 0; i < sum.length; i++) {
        sums += sum[i];
    }
    return sums/sum.length
}

function GetStandard(sum) {
    let avg = GetAverage(sum);
    let sums = 0;
    for (let i = 0; i < sum.length; i++) {
        sums +=(Number(arr[i])- avg)*(Number(arr[i])- avg)
    }
    let sd = (Math.sqrt(sums/sum.length)).toFixed(3);
    return sd;
}

describe("KvStoreTest", function () {
    const config = {
        bundleName : TEST_BUNDLE_NAME,
        userInfo : {
            userId : '0',
            userType : factory.UserType.SAME_USER_ID
        }
    }

    const options = {
        createIfMissing : true,
        encrypt : false,
        backup : false,
        autoSync : true,
        kvStoreType : factory.KVStoreType.DEVICE_COLLABORATION,
        schema : '',
        securityLevel : factory.SecurityLevel.S2,
    }

    beforeAll(async function (done) {
        console.info('beforeAll called')
        await factory.createKVManager(config).then((manager) => {
            kvManager = manager;
            console.info('beforeAll createKVManager success');
        }).catch((err) => {
            console.info('beforeAll createKVManager err ' + err);
        });
        await kvManager.getKVStore(TEST_STORE_ID, options).then((store) => {
            kvStore = store;
            console.info('beforeAll getKVStore for getDeviceId success');
        }).catch((err) => {
            console.info('beforeAll getKVStore err ' + err);
        });
        await kvManager.closeKVStore(TEST_BUNDLE_NAME, TEST_STORE_ID, kvStore);
        await kvManager.deleteKVStore(TEST_BUNDLE_NAME, TEST_STORE_ID);
        kvStore = null;
        console.info('beforeAll end');
        done();
    })

    afterAll(async function (done) {
        console.info('afterAll called')
        console.info('afterAll');
        kvManager = null;
        kvStore = null;
        done();
    })

    beforeEach(async function (done) {
        console.info('beforeEach called')
        await kvManager.getKVStore(TEST_STORE_ID, options, function (err, store) {
            kvStore = store;
            console.info('beforeEach getKVStore success');
            done();
        });
    })

    afterEach(async function (done) {
        console.info('afterEach called')
        await kvManager.closeKVStore(TEST_BUNDLE_NAME, TEST_STORE_ID, kvStore, async function (err, data) {
            console.info('afterEach closeKVStore success');
            await kvManager.deleteKVStore(TEST_BUNDLE_NAME, TEST_STORE_ID, function (err, data) {
                console.info('afterEach deleteKVStore success');
                done();
            });
        });
        kvStore = null;
    })

    /*
     * @tc.name:BenchnarkKvTestPromisePut01
     * @tc.desc:Test the efficiency of a large number of functions
     * @tc.type: FUNC
     * @tc.require: issueNumber.
     */
    it("BenchnarkKvTestPromisePut01", 0, async function (done) {
        var aggregate = [];
        for (let i = 0; i < 1000; i++) {
            var start = Date.now();
            try {
                await kvStore.put(KEY_TEST_STRING_ELEMENT, null).then((data) => {
                    console.info('BenchnarkKvTestPromisePut01 put success');
                    expect(null).assertFail();
                }).catch((error) => {
                    console.info('BenchnarkKvTestPromisePut01 put error' + error);
                });
            }catch (e) {
                console.info('BenchnarkKvTestPromisePut01 put e' + e);
                expect(null).assertFail();
            }
            var end = Date.now() - start;
            aggregate.push(end);
            await kvStore.delete(KEY_TEST_STRING_ELEMENT).then((data) => {
                console.info('BenchnarkKvTestPromisePut01 delete success');
                expect(err == undefined).assertTrue();
            });
        }
        var average = GetAverage(aggregate);
        var standard = GetStandard(aggregate);
        console.log("BenchnarkKvTestPromisePut01 average: "  + average);
        console.log("BenchnarkKvTestPromisePut01 standard: "  + standard);
        done();
    })

    /*
     * @tc.name:BenchnarkKvTestPromiseGet01
     * @tc.desc:Test the efficiency of a large number of functions
     * @tc.type: FUNC
     * @tc.require: issueNumber.
     */
    it("BenchnarkKvTestPromiseGet01", 0, async function (done) {
        var aggregate = [];
        await kvStore.put(KEY_TEST_STRING_ELEMENT, str).then(async (data) => {
            console.info('BenchnarkKvTestPromiseGet01 put success');
            expect(err == undefined).assertTrue();
        });
        for (let i = 0; i < 1000; i++) {
            var start = Date.now();
            try {
                await kvStore.get(localDeviceId, KEY_TEST_STRING_ELEMENT).then((data) => {
                    console.info('BenchnarkKvTestPromiseGet01 get success data ' + data);
                    expect((err == undefined) && (VALUE_TEST_INT_ELEMENT == data)).assertTrue();
                });
            }catch(e) {
                console.info('BenchnarkKvTestPromiseGet01 get e' + e);
                expect(null).assertFail();
            }
            var end = Date.now() - start;
            aggregate.push(end);
        }
        await kvStore.delete(KEY_TEST_STRING_ELEMENT).then((data) => {
            console.info('BenchnarkKvTestPromiseGet01 delete success');
            expect(err == undefined).assertTrue();
        });
        var average = GetAverage(aggregate);
        var standard = GetStandard(aggregate);
        console.log("BenchnarkKvTestPromiseGet01 average: "  + average);
        console.log("BenchnarkKvTestPromiseGet01 standard: "  + standard);
        done();
    })

    /*
     * @tc.name:BenchnarkKvTestPromiseDelete01
     * @tc.desc:Test the efficiency of a large number of functions
     * @tc.type: FUNC
     * @tc.require: issueNumber.
     */
    it("BenchnarkKvTestPromiseDelete01", 0, async function (done) {
        var aggregate = [];
        for (let i = 0; i < 1000; i++) {
            await kvStore.put(KEY_TEST_STRING_ELEMENT, str).then(async (data) => {
                console.info('BenchnarkKvTestPromiseDelete01 put success');
                expect(err == undefined).assertTrue();
            });
            var start = Date.now();
            try {
                await kvStore.delete(KEY_TEST_STRING_ELEMENT).then((data) => {
                    console.info('BenchnarkKvTestPromiseDelete01 delete success');
                    expect(err == undefined).assertTrue();
                });
            }catch(e) {
                console.info('BenchnarkKvTestPromiseDelete01 delete e' + e);
                expect(null).assertFail();
            }
            var end = Date.now() - start;
            aggregate.push(end);
        }
        var average = GetAverage(aggregate);
        var standard = GetStandard(aggregate);
        console.log("BenchnarkKvTestPromiseDelete01 average: "  + average);
        console.log("BenchnarkKvTestPromiseDelete01 standard: "  + standard);
        done();
    })

    /*
     * @tc.name:BenchnarkKvTestPromisePutBatch01
     * @tc.desc:Test the efficiency of a large number of functions
     * @tc.type: FUNC
     * @tc.require: issueNumber.
     */
    it("BenchnarkKvTestPromisePutBatch01", 0, async function (done) {
        let entries = [];
        let keys = [];
        for (var i = 0; i < 10; i++) {
            var key = 'batch_test_string_key';
            var entry = {
                key : key + i,
                value : {
                    type : factory.ValueType.STRING,
                    value : 'batch_test_string_value'
                }
            }
            entries.push(entry);
            keys.push(key + i);
        }
        var aggregate = [];
        for (let i = 0; i < 1000; i++) {
            var start = Date.now();
            try {
                await kvStore.putBatch(entries).then(async (err) => {
                    console.info('BenchnarkKvTestPromisePutBatch01 putBatch success');
                    expect(err == undefined).assertTrue();
                });
            }catch(e) {
                console.info('BenchnarkKvTestPromisePutBatch01 delete e' + e);
                expect(null).assertFail();
            }
            var end = Date.now() - start;
            aggregate.push(end);
            await kvStore.deleteBatch(keys).then((err) => {
                console.info('BenchnarkKvTestPromisePutBatch01 deleteBatch success');
                expect(err == undefined).assertTrue();
            });
        }
        var average = GetAverage(aggregate);
        var standard = GetStandard(aggregate);
        console.log("BenchnarkKvTestPromisePutBatch01 average: "  + average);
        console.log("BenchnarkKvTestPromisePutBatch01 standard: "  + standard);
        done();
    })

    /*
     * @tc.name:BenchnarkKvTestPromiseDeleteBatch01
     * @tc.desc:Test the efficiency of a large number of functions
     * @tc.type: FUNC
     * @tc.require: issueNumber.
     */
    it("BenchnarkKvTestPromiseDeleteBatch01", 0, async function (done) {
        let entries = [];
        let keys = [];
        for (var i = 0; i < 10; i++) {
            var key = 'batch_test_string_key';
            var entry = {
                key : key + i,
                value : {
                    type : factory.ValueType.STRING,
                    value : 'batch_test_string_value'
                }
            }
            entries.push(entry);
            keys.push(key + i);
        }
        var aggregate = [];
        for (let i = 0; i < 1000; i++) {
            await kvStore.putBatch(entries).then(async (err) => {
                console.info('BenchnarkKvTestPromiseDeleteBatch01 putBatch success');
                expect(err == undefined).assertTrue();
            });
            var start = Date.now();
            try {
                await kvStore.deleteBatch(keys).then((err) => {
                    console.info('BenchnarkKvTestPromiseDeleteBatch01 deleteBatch success');
                    expect(err == undefined).assertTrue();
                });
            }catch(e) {
                console.info('BenchnarkKvTestPromiseDeleteBatch01 delete e' + e);
                expect(null).assertFail();
            }
            var end = Date.now() - start;
            aggregate.push(end);
        }
        var average = GetAverage(aggregate);
        var standard = GetStandard(aggregate);
        console.log("BenchnarkKvTestPromiseDeleteBatch01 average: "  + average);
        console.log("BenchnarkKvTestPromiseDeleteBatch01 standard: "  + standard);
        done();
    })

    /*
     * @tc.name:BenchnarkKvTestPromisegetEntries01
     * @tc.desc:Test the efficiency of a large number of functions
     * @tc.type: FUNC
     * @tc.require: issueNumber.
     */
    it("BenchnarkKvTestPromisegetEntries01", 0, async function (done) {
        let entries = [];
        let keys = [];
        for (var i = 0; i < 10; i++) {
            var key = 'batch_test_string_key';
            var entry = {
                key : key + i,
                value : {
                    type : factory.ValueType.STRING,
                    value : 'batch_test_string_value'
                }
            }
            entries.push(entry);
            keys.push(key + i);
        }
        await kvStore.putBatch(entries, async function (err,data) {
            console.info('BenchnarkKvTestPromisegetEntries01 putBatch success');
            expect(err == undefined).assertTrue();
        });
        var aggregate = [];
        for (let i = 0; i < 1000; i++) {
            var start = Date.now();
            try {
                await kvStore.getEntries(localDeviceId, query).then((entrys) => {
                    console.info('BenchnarkKvTestPromisegetEntries01 getEntries success');
                });
            }catch(e) {
                console.info('BenchnarkKvTestPromisegetEntries01 delete e' + e);
                expect(null).assertFail();
            }
            var end = Date.now() - start;
            aggregate.push(end);
        }
        await kvStore.deleteBatch(keys).then((err) => {
            console.info('BenchnarkKvTestPromisegetEntries01 deleteBatch success');
            expect(err == undefined).assertTrue();
        });
        var average = GetAverage(aggregate);
        var standard = GetStandard(aggregate);
        console.log("BenchnarkKvTestPromisegetEntries01 average: "  + average);
        console.log("BenchnarkKvTestPromisegetEntries01 standard: "  + standard);
        done();
    })
})